package com.can.service;

import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.baomidou.mybatisplus.mapper.Condition;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.can.common.ITreeNodeAdapter;
import com.can.common.constant.WebConstants;
import com.can.common.exception.EntityException;
import com.can.common.exception.ServiceException;
import com.can.entityDTO.TreeNode;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

/**
 * @Description 通用基础service 实现类
 * @Author can
 * @Date 2018/10/20
 * @Version 1.0
 */
public abstract class BaseServiceImpl<T> implements IBaseService<T> {
    // 主键
    private final String ID_KEY = "id";
    // 操作数据库失败返回记录数
    private final Integer RESULT_ROW = 0;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer save(T entity) throws ServiceException {
        Field field = null;
        try {
            getMapper().insert(entity);
            field = entity.getClass().getDeclaredField(ID_KEY);
            field.setAccessible(true);
            if (null == field.get(entity)) {
                throw new EntityException(entity.getClass().getName() + ":" + ID_KEY + "值为空");
            }
            return (Integer) field.get(entity);
        }catch (DuplicateKeyException e){
            throw new ServiceException("名称、页面编码、网址其中一个已经存在了",e);
        }catch (Exception e){
            throw new ServiceException("添加失败",e);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean updateById(T entity) {
        try {
            Integer result = getMapper().updateById(entity);
            if(RESULT_ROW.equals(result)){
                throw new ServiceException("更新失败");
            }
            return true;
        }catch (DuplicateKeyException e){
            throw new ServiceException("名称、页面编码、网址其中一个已经存在了",e);
        }catch (Exception e){
            throw new ServiceException("更新失败",e);
        }
    }

    @Override
    public T selectById(Serializable id) {
        if (null == id) {
            throw new ServiceException("id不能为空");
        }
        Condition condition = new Condition();
        condition.where("id={0}",id.toString());
        condition.where("unit_id={0}", WebConstants.DEFAULT_UNIT_ID);
        List<T> result = getMapper().selectList(condition);
        if(CollectionUtils.isEmpty(result)){
            return null;
        }
        return result.get(0);
    }

    @Override
    public List<T> selectList(T entity) {
        EntityWrapper<T> wrapper = new EntityWrapper<T>(entity);
        wrapper.where("unit_id={0}", WebConstants.DEFAULT_UNIT_ID);
        return getMapper().selectList(wrapper);
    }

    @Override
    public Page<T> selectPage(Page<T> page, Wrapper<T> wrapper) {
        wrapper.where("unit_id={0}", WebConstants.DEFAULT_UNIT_ID);
        List<T> list = getMapper().selectPage(page, wrapper);
        return page.setRecords(list);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean deleteBatchIds(Collection<? extends Serializable> idList) {
        if(CollectionUtils.isEmpty(idList)){
            throw new ServiceException("id不能为空");
        }
        try {
            Integer result = getMapper().deleteBatchIds(idList);
            if(RESULT_ROW.equals(result)){
                throw new ServiceException("删除失败");
            }
            return true;
        }catch (Exception e){
            throw new ServiceException("删除失败",e);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean deleteById(Serializable id) {
        if (null == id) {
            throw new ServiceException("id不能为空");
        }
        try {
            Integer result = getMapper().deleteById(id);
            if(RESULT_ROW.equals(result)){
                throw new ServiceException("删除失败");
            }
            return true ;
        }catch (Exception e){
            throw new ServiceException("删除失败",e);
        }
    }

    /**
     * 将数据集list转换成树节点TreeNode list
     * @param resList
     * @return
     */
    private List<TreeNode<T>> convertTreeNodeList(List<T> resList, ITreeNodeAdapter<T> adapter){
        List<TreeNode<T>> resultList = new LinkedList<TreeNode<T>>();
        if(CollectionUtils.isEmpty(resList)){
            return resultList;
        }
        for(T entity : resList){
            resultList.add(adapter.covert(entity));
        }
        return resultList;
    }

    /**
     * 将树节点TreeNode list 转成树
     * @param resList 实体list
     * @param adapter 转换器
     * @return
     */
    protected List<TreeNode<T>> buildTreeList(List<T> resList, ITreeNodeAdapter<T> adapter){
        List<TreeNode<T>> treeList = convertTreeNodeList(resList,adapter);
        List<TreeNode<T>> resultList = new LinkedList<TreeNode<T>>();
        if(CollectionUtils.isEmpty(treeList)){
            return treeList;
        }
        for(int i = 0; i < treeList.size(); i++) {
            if(0 == treeList.get(i).getfId() || null == treeList.get(i).getfId()){
                resultList.add(treeList.get(i));
            }
            for(int j = 0; j < treeList.size(); j++){
                if(treeList.get(i).getId().equals(treeList.get(j).getfId())){
                    if(null == treeList.get(i).getChildren()){
                        treeList.get(i).setChildren(new LinkedList<TreeNode<T>>());
                    }
                    treeList.get(i).getChildren().add(treeList.get(j));
                }else if(treeList.get(j).getId().equals(treeList.get(i).getfId())){
                    if(null == treeList.get(j).getChildren()){
                        treeList.get(j).setChildren(new LinkedList<TreeNode<T>>());
                    }
                    treeList.get(j).getChildren().add(treeList.get(i));
                }
            }
            treeList.remove(i);
            i--;
        }
        return resultList;
    }

    protected abstract BaseMapper<T> getMapper();
}
